import { createStoreBindings } from "mobx-miniprogram-bindings";
import { globalStore } from "../../../store/index";
import { fetchMenu, updateMenu, createMenu, removeMenu } from "../../../services/dish";
import { appConfig } from "../../../config/appConfig";
import { toast } from "../../../utils/toast";
import type { MenuItem } from "../../../types/entities";
import type { MenuCreatePayload } from "../../../types/dto";

type CategoryOption = { key: string; name: string; icon?: string };

Page({
  data: {
    loading: true,
    categoryList: [] as CategoryOption[],
    activeCategory: "all",
    menuList: [] as MenuItem[],
    filteredList: [] as MenuItem[],
    summaryInfo: {
      totalItems: 0,
      totalStock: 0,
      funAvg: 0,
    },
    highlights: [] as MenuItem[],
    showCreatePanel: false,
    createForm: {
      name: "",
      categoryKey: "",
      description: "",
      coverUrl: "",
      stock: 0,
      funValue: 0,
      isActive: true,
    } as MenuCreatePayload,
    createCategoryIndex: 0,
    uploadingCover: false,
    creating: false,
    showEditPanel: false,
    editingId: "",
    editingName: "",
    editStock: 0,
    editFunValue: 0,
    saving: false,
  },

  storeBindings: null as WechatMiniprogram.Component.TrivialInstance | null,

  onLoad() {
    this.storeBindings = createStoreBindings(this, {
      store: globalStore,
      fields: ["menu"],
      actions: ["setMenu", "updateMenuSnapshot"],
    });
  },

  onUnload() {
    this.storeBindings?.destroyStoreBindings?.();
  },

  async onShow() {
    await this.loadMenu();
  },

  async loadMenu() {
    this.setData({ loading: true });
    try {
      const res = await fetchMenu();
      globalStore.setMenu(res.menu);
      this.setupCategories(res.menu);
      this.updateSummary(res.menu);
      this.applyFilter(this.data.activeCategory, res.menu);
    } catch (error) {
      console.error("加载菜单失败", error);
      wx.showToast({ title: "加载失败", icon: "none" });
    } finally {
      this.setData({ loading: false });
    }
  },

  getCategoryOptions(): CategoryOption[] {
    if (this.data.categoryList.length) {
      return this.data.categoryList;
    }
    const set = new Map<string, CategoryOption>();
    (globalStore.categories || []).forEach((category) => {
      if (!set.has(category.key)) {
        set.set(category.key, {
          key: category.key,
          name: category.name,
          icon: category.icon,
        });
      }
    });
    (globalStore.menu || []).forEach((item) => {
      if (!set.has(item.categoryKey)) {
        set.set(item.categoryKey, this.decorateCategory(item.categoryKey));
      }
    });
    return Array.from(set.values());
  },

  setupCategories(menu: MenuItem[]) {
    const set = new Map<string, CategoryOption>();
    (globalStore.categories || []).forEach((category) => {
      if (!set.has(category.key)) {
        set.set(category.key, {
          key: category.key,
          name: category.name,
          icon: category.icon,
        });
      }
    });
    menu.forEach((item) => {
      if (!set.has(item.categoryKey)) {
        set.set(item.categoryKey, this.decorateCategory(item.categoryKey));
      }
    });
    const categoryList: CategoryOption[] = Array.from(set.values());
    this.setData({ categoryList });
  },

  decorateCategory(key: string): CategoryOption {
    const matched = (globalStore.categories || []).find((item) => item.key === key);
    if (matched) {
      return { key, name: matched.name, icon: matched.icon };
    }
    const presets: Record<string, CategoryOption> = {
      stirfry: { key, name: "热炒", icon: "🍲" },
      rice: { key, name: "主食", icon: "🍚" },
      fruit: { key, name: "鲜果", icon: "🍉" },
      snack: { key, name: "小食", icon: "🍡" },
      whole: { key, name: "粗粮", icon: "🥖" },
      dessert: { key, name: "甜品", icon: "🍰" },
      drink: { key, name: "饮品", icon: "🧃" },
    };
    const preset = presets[key];
    if (preset) return preset;
    return {
      key,
      name: key,
      icon: "🥗",
    };
  },

  updateSummary(menu: MenuItem[]) {
    const totalItems = menu.length;
    const totalStock = menu.reduce((sum, item) => sum + (item.stock || 0), 0);
    const funTotal = menu.reduce((sum, item) => sum + (item.funValue || 0), 0);
    const funAvg = totalItems ? Math.round((funTotal / totalItems) * 10) / 10 : 0;
    const highlights = [...menu].sort((a, b) => b.funValue - a.funValue).slice(0, 3);
    this.setData({
      summaryInfo: {
        totalItems,
        totalStock,
        funAvg,
      },
      highlights,
    });
  },

  applyFilter(categoryKey: string, menuList?: MenuItem[]) {
    const source = menuList ?? this.data.menuList;
    const filtered =
      categoryKey === "all"
        ? source
        : source.filter((item) => item.categoryKey === categoryKey);
    this.setData({ menuList: source, filteredList: filtered, activeCategory: categoryKey });
  },

  handleCategoryTap(event: WechatMiniprogram.BaseEvent) {
    const { key } = event.currentTarget.dataset as { key: string };
    this.applyFilter(key);
  },

  handleOpenCreate() {
    const categoryList = this.getCategoryOptions();
    if (!categoryList.length) {
      wx.showModal({
        title: "暂无分类",
        content: "请先在后台配置菜品分类后再试。",
        showCancel: false,
      });
      return;
    }
    const fallbackCategory = categoryList[0]?.key || "";
    if (!fallbackCategory) {
      wx.showToast({ title: "请先同步分类", icon: "none" });
      return;
    }
    const defaultIndex = Math.max(
      0,
      categoryList.findIndex((item) => item.key === fallbackCategory)
    );
    const defaultForm: MenuCreatePayload = {
      name: "",
      categoryKey: fallbackCategory,
      description: "",
      coverUrl: "",
      stock: 0,
      funValue: 0,
      isActive: true,
    };
    this.setData({
      categoryList,
      showCreatePanel: true,
      createForm: defaultForm,
      createCategoryIndex: defaultIndex,
    });
  },

  handleCloseCreate() {
    this.setData({ showCreatePanel: false });
  },

  handleCreateInput(event: WechatMiniprogram.CustomEvent<{ value: string }>) {
    const { field } = event.currentTarget.dataset as { field: keyof MenuCreatePayload };
    if (!field) return;
    const value = event.detail.value;
    if (field === "stock" || field === "funValue") {
      const num = Math.max(0, Number(value || 0));
      this.setData({ [`createForm.${field}`]: num });
      return;
    }
    this.setData({ [`createForm.${field}`]: value });
  },

  handleCreateStep(event: WechatMiniprogram.BaseEvent) {
    const { field, delta } = event.currentTarget.dataset as {
      field: "stock" | "funValue";
      delta: "inc" | "dec";
    };
    if (!field) return;
    const current = this.data.createForm[field] || 0;
    const step = delta === "dec" ? -1 : 1;
    const next = Math.max(0, current + step);
    this.setData({ [`createForm.${field}`]: next });
  },

  handleCreateCategoryChange(event: WechatMiniprogram.CustomEvent<{ value: number }>) {
    const index = Number(event.detail.value ?? 0);
    const category = this.data.categoryList[index];
    if (!category) return;
    this.setData({
      createCategoryIndex: index,
      "createForm.categoryKey": category.key,
    });
  },

  handleCreateToggleStatus(event: WechatMiniprogram.CustomEvent<{ value: boolean }>) {
    const value = !!event.detail.value;
    this.setData({ "createForm.isActive": value });
  },

  handlePickCover() {
    if (this.data.uploadingCover) return;
    wx.chooseImage({
      count: 1,
      sizeType: ["compressed"],
      sourceType: ["album", "camera"],
      success: async (res) => {
        const filePath = res.tempFilePaths?.[0];
        if (!filePath) return;
        let coverUrl = filePath;
        if (appConfig.useCloud && typeof wx.cloud?.uploadFile === "function") {
          const ext = filePath.split(".").pop() || "jpg";
          const cloudPath = `menu/${Date.now()}_${Math.random()
            .toString(16)
            .slice(2)}.${ext}`;
          this.setData({ uploadingCover: true });
          try {
            const uploadRes = await wx.cloud.uploadFile({
              cloudPath,
              filePath,
            });
            coverUrl = uploadRes.fileID;
          } catch (error) {
            console.error("upload cover failed", error);
            wx.showToast({ title: "上传失败", icon: "none" });
            this.setData({ uploadingCover: false });
            return;
          }
          this.setData({ uploadingCover: false });
        }
        this.setData({ "createForm.coverUrl": coverUrl });
        toast("已选择封面");
      },
      fail: (err) => {
        if (err?.errMsg?.includes("cancel")) return;
        console.error("choose image failed", err);
        wx.showToast({ title: "无法选择图片", icon: "none" });
      },
    });
  },

  validateCreateForm(form: MenuCreatePayload) {
    if (!form.name || !form.name.trim()) {
      wx.showToast({ title: "请填写菜品名称", icon: "none" });
      return false;
    }
    if (!form.categoryKey) {
      wx.showToast({ title: "请选择分类", icon: "none" });
      return false;
    }
    if (!form.coverUrl) {
      wx.showToast({ title: "请上传图片", icon: "none" });
      return false;
    }
    return true;
  },

  async handleCreateSubmit() {
    if (this.data.creating) return;
    const form = this.data.createForm;
    const payload: MenuCreatePayload = {
      ...form,
      name: form.name?.trim() || "",
      description: form.description?.trim() || "",
      stock: Math.max(0, Number(form.stock || 0)),
      funValue: Math.max(0, Number(form.funValue || 0)),
      isActive: form.isActive ?? true,
    };
    if (!this.validateCreateForm(payload)) return;
    this.setData({ creating: true });
    try {
      const res = await createMenu(payload);
      globalStore.updateMenuSnapshot(res.menu);
      toast("菜品已创建");
      this.setData({ showCreatePanel: false });
      this.setupCategories(globalStore.menu);
      this.updateSummary(globalStore.menu);
      this.applyFilter(this.data.activeCategory, globalStore.menu);
    } catch (error) {
      console.error("create menu failed", error);
      wx.showToast({ title: "创建失败", icon: "none" });
    } finally {
      this.setData({ creating: false });
    }
  },

  handleOpenEdit(event: WechatMiniprogram.BaseEvent) {
    const { id } = event.currentTarget.dataset as { id: string };
    const target = this.data.menuList.find((item) => item._id === id);
    if (!target) return;
    this.setData({
      showEditPanel: true,
      editingId: target._id,
      editingName: target.name,
      editStock: target.stock,
      editFunValue: target.funValue,
    });
  },

  handleCloseEdit() {
    this.setData({ showEditPanel: false, editingId: "" });
  },

  handleStep(event: WechatMiniprogram.BaseEvent) {
    const { type } = event.currentTarget.dataset as { type: "stock" | "fun"; delta: "inc" | "dec" } & { delta?: "inc" | "dec" };
    const delta = event.currentTarget.dataset.delta === "dec" ? -1 : 1;
    if (type === "stock") {
      const value = Math.max(0, this.data.editStock + delta);
      this.setData({ editStock: value });
    } else {
      const value = Math.max(0, this.data.editFunValue + delta);
      this.setData({ editFunValue: value });
    }
  },

  handleStockInput(event: WechatMiniprogram.CustomEvent<{ value: string }>) {
    const value = Math.max(0, Number(event.detail.value || 0));
    this.setData({ editStock: value });
  },

  handleFunInput(event: WechatMiniprogram.CustomEvent<{ value: string }>) {
    const value = Math.max(0, Number(event.detail.value || 0));
    this.setData({ editFunValue: value });
  },

  async handleSaveEdit() {
    if (!this.data.editingId || this.data.saving) return;
    this.setData({ saving: true });
    try {
      const res = await updateMenu({
        _id: this.data.editingId,
        stock: this.data.editStock,
        funValue: this.data.editFunValue,
      });
      globalStore.updateMenuSnapshot(res.menu);
      toast("已更新库存");
      this.handleCloseEdit();
      this.applyFilter(this.data.activeCategory, globalStore.menu);
    } catch (error) {
      console.error("更新库存失败", error);
      toast((error as Error).message || "保存失败");
    } finally {
      this.setData({ saving: false });
    }
  },

  handleDeleteDish(event: WechatMiniprogram.BaseEvent) {
    const { id, name } = event.currentTarget.dataset as { id: string; name?: string };
    if (!id) return;
    wx.showModal({
      title: "删除菜品",
      content: `确定删除「${name || "该菜品"}」吗？`,
      confirmText: "删除",
      confirmColor: "#d64561",
      success: async (res) => {
        if (!res.confirm) return;
        try {
          await removeMenu(id);
          globalStore.removeMenuSnapshot(id);
          toast("已删除");
          this.setupCategories(globalStore.menu);
          this.updateSummary(globalStore.menu);
          this.applyFilter(this.data.activeCategory, globalStore.menu);
        } catch (error) {
          console.error("delete menu failed", error);
          wx.showToast({ title: "删除失败", icon: "none" });
        }
      },
    });
  },
});
